package com.zbkj.dal.pojo.response;

import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

import lombok.Getter;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.util.CollectionUtils;

/**
 * @author JXY
 * @date 2024/01/30
 */
@Getter
public class PageImpl<R> implements Serializable {
    private static final long serialVersionUID = 1L;
    private List<R> content;
    private long totalPages;
    private long totalElements;
    private int size;
    private int page;

    public static <R> PageImpl<R> of() {
        PageImpl<R> pageImpl = new PageImpl<>();
        pageImpl.content = Collections.emptyList();
        return pageImpl;
    }

    public boolean isEmpty() {
        List<R> itemList = this.content;
        return CollectionUtils.isEmpty(itemList);
    }

    public static <T, R> PageImpl<R> of(PageImpl<T> page, Function<T, R> function) {
        PageImpl<R> pageImpl = new PageImpl<>();
        pageImpl.totalElements = page.getTotalElements();
        pageImpl.totalPages = page.getTotalPages();
        pageImpl.size = page.getSize();
        pageImpl.page = page.getPage();
        pageImpl.content = page.getContent().stream().map(function).collect(Collectors.toList());
        return pageImpl;
    }

    public static <R> PageImpl<R> empty(int page, int size) {
        PageImpl<R> pageImpl = new PageImpl<>();
        pageImpl.content = Collections.emptyList();
        pageImpl.size = size;
        pageImpl.page = page;
        pageImpl.totalElements = 0L;
        pageImpl.totalPages = 0L;
        return pageImpl;
    }

    public static <T, R> PageImpl<R> of(Page<T> page, Function<T, R> function) {
        PageImpl<R> pageImpl = new PageImpl<>();
        pageImpl.totalElements = page.getTotalElements();
        pageImpl.totalPages = page.getTotalPages();
        pageImpl.size = page.getSize();
        pageImpl.page = page.getNumber();
        pageImpl.content = page.getContent().stream().map(function).collect(Collectors.toList());
        return pageImpl;
    }

    public static <R> PageImpl<R> of(Page<R> page) {
        PageImpl<R> pageImpl = new PageImpl<>();
        pageImpl.totalElements = page.getTotalElements();
        pageImpl.totalPages = page.getTotalPages();
        pageImpl.size = page.getSize();
        pageImpl.page = page.getNumber();
        pageImpl.content = page.getContent();
        return pageImpl;
    }

    public static <R> PageImpl<R> of(List<R> content, Pageable request, long totalElements) {
        PageImpl<R> pageImpl = new PageImpl<>();
        pageImpl.totalElements = totalElements;
        pageImpl.totalPages = totalElements % (long)request.getPageSize() == 0L ? totalElements / (long)request.getPageSize() : totalElements / (long)request.getPageSize() + 1L;
        pageImpl.size = request.getPageSize();
        pageImpl.page = request.getPageNumber();
        pageImpl.content = content;
        return pageImpl;
    }

    public static <R> PageImpl<R> of(List<R> content, int page, int size, long totalElements) {
        PageImpl<R> pageImpl = new PageImpl<>();
        pageImpl.totalElements = totalElements;
        pageImpl.totalPages = totalElements % (long)size == 0L ? totalElements / (long)size : totalElements / (long)size + 1L;
        pageImpl.size = size;
        pageImpl.page = page;
        pageImpl.content = content;
        return pageImpl;
    }

    private PageImpl() {
    }
}
